package lcd

import (
	"sync"
	"time"
)

// MenuItemType 定义菜单项类型
type MenuItemType int

const (
	MenuItemTypeNormal MenuItemType = iota // 普通菜单项
	MenuItemTypeValue                      // 可调节数值的菜单项
)

// MenuItem 定义菜单项结构
type MenuItem struct {
	ID       string       // 菜单项唯一标识
	Type     MenuItemType // 菜单项类型
	Display  string       // 显示内容
	Value    *int         // 当Type为MenuItemTypeValue时的当前值
	MinValue *int         // 最小值
	MaxValue *int         // 最大值
	Step     *int         // 调节步长
	Children []*MenuItem  // 子菜单项
	Parent   *MenuItem    // 父菜单项
	Action   func()       // 菜单项的动作
}

// AddChild 添加子菜单项
func (m *MenuItem) AddChild(child *MenuItem) {
	child.Parent = m
	if m.Children == nil {
		m.Children = make([]*MenuItem, 0)
	}
	m.Children = append(m.Children, child)
}

// Menu 菜单管理器
type Menu struct {
	mu        sync.RWMutex
	status    MenuStatus
	bakStatus MenuStatus
	display   *Display
	msgCh     chan MenuMsg
	quit      chan struct{} // 退出通道
}

// NewMenu 创建新的菜单管理器
func NewMenu(display *Display) *Menu {
	m := &Menu{
		display: display,
		msgCh:   make(chan MenuMsg, 10),
		quit:    make(chan struct{}),
	}

	// 初始化为状态模式
	m.status.Mode = MenuModeStat
	m.status.StatOpt = StatOptIdle
	m.bakStatus = m.status

	go m.run()
	return m
}

// run 运行菜单消息处理循环
func (m *Menu) run() {
	ticker := time.NewTicker(100 * time.Millisecond)
	defer ticker.Stop()

	for {
		select {
		case msg := <-m.msgCh:
			switch msg.ID {
			case MenuMsgIDUpdateImmediately:
				m.mu.Lock()
				if m.status.Mode != MenuModeTip {
					m.bakStatus = m.status
				}
				ret := m.doMsgUpdateImmediately(msg.P1)
				if ret == 0 {
					m.selectMenuByPriority()
					m.status.DispCnter = 0
					m.updateDisplay()
				}
				m.mu.Unlock()
			}
		case <-ticker.C:
			m.mu.Lock()
			m.status.DispCnter++
			m.updateDisplay()
			m.mu.Unlock()
		case <-m.quit:
			// 清理显示
			m.mu.Lock()
			m.display.Clear()
			m.display.Close()
			m.mu.Unlock()
			return
		}
	}
}

// updateDisplay 更新显示内容
func (m *Menu) updateDisplay() {
	switch m.status.Mode {
	case MenuModeStat:
		m.showStat()
	case MenuModeView:
		m.showView()
	case MenuModeMenu:
		m.showMenu()
	case MenuModeTip:
		m.showTip()
	}
}

func (m *Menu) doMsgUpdateImmediately(p1 uint32) int {
	ret := 0
	mode := MenuMode(p1 >> 16)
	opt := p1 & 0xff

	if mode == MenuModeStat {
		switch StatOpt(opt) {
		case StatOptIdle:
			m.status.Mode = MenuModeStat
			m.status.StatOpt = StatOptIdle
		case StatOptAutoHeat1:
			m.status.Mode = MenuModeStat
			m.status.StatOpt = StatOptAutoHeat1
		case StatOptAutoHeat2:
			m.status.Mode = MenuModeStat
			m.status.StatOpt = StatOptAutoHeat2
		case StatOptAutoHeat3:
			m.status.Mode = MenuModeStat
			m.status.StatOpt = StatOptAutoHeat3
		case StatOptAutoShot:
			m.status.Mode = MenuModeStat
			m.status.StatOpt = StatOptAutoShot
		case StatOptAutoHeat1Shot:
			m.status.Mode = MenuModeStat
			m.status.StatOpt = StatOptAutoHeat1Shot
		case StatOptAutoHeat2Shot:
			m.status.Mode = MenuModeStat
			m.status.StatOpt = StatOptAutoHeat2Shot
		case StatOptAutoHeat3Shot:
			m.status.Mode = MenuModeStat
			m.status.StatOpt = StatOptAutoHeat3Shot
		case StatOptAutoError:
			m.status.Mode = MenuModeStat
			m.status.StatOpt = StatOptAutoError
		case StatOptForceHeat1:
			m.status.Mode = MenuModeStat
			m.status.StatOpt = StatOptForceHeat1
		case StatOptForceHeat2:
			m.status.Mode = MenuModeStat
			m.status.StatOpt = StatOptForceHeat2
		case StatOptForceHeat3:
			m.status.Mode = MenuModeStat
			m.status.StatOpt = StatOptForceHeat3
		case StatOptForceShot:
			m.status.Mode = MenuModeStat
			m.status.StatOpt = StatOptForceShot
		case StatOptForceHeat1Shot:
			m.status.Mode = MenuModeStat
			m.status.StatOpt = StatOptForceHeat1Shot
		case StatOptForceHeat2Shot:
			m.status.Mode = MenuModeStat
			m.status.StatOpt = StatOptForceHeat2Shot
		case StatOptForceHeat3Shot:
			m.status.Mode = MenuModeStat
			m.status.StatOpt = StatOptForceHeat3Shot
		case StatOptWarn:
			m.status.Mode = MenuModeStat
			m.status.StatOpt = StatOptWarn
		default:
			ret = -1
		}
	} else if mode == MenuModeView {
		switch ViewOpt(opt) {
		case ViewOptTemperature:
			m.status.Mode = MenuModeView
			m.status.ViewOpt = ViewOptTemperature
		case ViewOptDuty:
			m.status.Mode = MenuModeView
			m.status.ViewOpt = ViewOptDuty
		case ViewOptOilData:
			m.status.Mode = MenuModeView
			m.status.ViewOpt = ViewOptOilData
		case ViewOptSmokeSensor:
			m.status.Mode = MenuModeView
			m.status.ViewOpt = ViewOptSmokeSensor
		default:
			ret = -1
		}
	} else if mode == MenuModeMenu {
		switch MenuOpt(opt) {
		case MenuOptT0:
			m.status.Mode = MenuModeMenu
			m.status.MenuOpt = MenuOptT0
		case MenuOptT1:
			m.status.Mode = MenuModeMenu
			m.status.MenuOpt = MenuOptT1
		case MenuOptT2:
			m.status.Mode = MenuModeMenu
			m.status.MenuOpt = MenuOptT2
		case MenuOptT3:
			m.status.Mode = MenuModeMenu
			m.status.MenuOpt = MenuOptT3
		case MenuOptT4:
			m.status.Mode = MenuModeMenu
			m.status.MenuOpt = MenuOptT4
		case MenuOptT5:
			m.status.Mode = MenuModeMenu
			m.status.MenuOpt = MenuOptT5
		case MenuOptP0:
			m.status.Mode = MenuModeMenu
			m.status.MenuOpt = MenuOptP0
		case MenuOptP1:
			m.status.Mode = MenuModeMenu
			m.status.MenuOpt = MenuOptP1
		case MenuOptPDef:
			m.status.Mode = MenuModeMenu
			m.status.MenuOpt = MenuOptPDef
		case MenuOptOilLimit:
			m.status.Mode = MenuModeMenu
			m.status.MenuOpt = MenuOptOilLimit
		case MenuOptWaterLimit:
			m.status.Mode = MenuModeMenu
			m.status.MenuOpt = MenuOptWaterLimit
		default:
			ret = -1
		}
	} else if mode == MenuModeTip {
		switch TipOpt(opt) {
		case TipOptOK:
			m.status.Mode = MenuModeTip
			m.status.TipOpt = TipOptOK
		case TipOptErr:
			m.status.Mode = MenuModeTip
			m.status.TipOpt = TipOptErr
		case TipOptBLEUpgradeApp:
			m.status.Mode = MenuModeTip
			m.status.TipOpt = TipOptBLEUpgradeApp
		default:
			ret = -1
		}
	} else {
		ret = -1
	}

	return ret
}

func (m *Menu) selectMenuByPriority() {
	/*
		mode := m.status.Mode
		pro := project_get()
		flag := byte(0x00)
		// TODO: 实现菜单优先级选择逻辑
		// 1. 状态模式下的处理
		if mode == MenuModeStat {
			// 1.1 自动模式
			if autoStart || autoEnding {
				// 检查油泵状态
				if oilPumpAllOpened {
					flag = 0x01
					// 检查加热器状态
					if heater1Opened {
						flag |= (0x01 << 1)
					}
					if heater2Opened {
						flag |= (0x01 << 2)
					}
				} else {
					flag = 0x00
					// 检查加热器状态
					if heater1Opened {
						flag |= (0x01 << 1)
					}
					if heater2Opened {
						flag |= (0x01 << 2)
					}
				}

				// 根据状态标志设置显示选项
				switch flag {
				case 0x00:
					m.status.StatOpt = StatOptAutoError
				case 0x01:
					m.status.StatOpt = StatOptAutoShot
				case 0x02:
					m.status.StatOpt = StatOptAutoHeat1
				case 0x03:
					m.status.StatOpt = StatOptAutoHeat1Shot
				case 0x04:
					m.status.StatOpt = StatOptAutoHeat2
				case 0x05:
					m.status.StatOpt = StatOptAutoHeat2Shot
				case 0x06:
					m.status.StatOpt = StatOptAutoHeat3
				case 0x07:
					m.status.StatOpt = StatOptAutoHeat3Shot
				}
			} else {
				// 1.2 手动模式
				if forceOilPump {
					flag = 0x01
					if forceHeat1 {
						flag |= (0x01 << 1)
					}
					if forceHeat2 {
						flag |= (0x01 << 2)
					}
				} else {
					flag = 0x00
					if forceHeat1 {
						flag |= (0x01 << 1)
					}
					if forceHeat2 {
						flag |= (0x01 << 2)
					}
				}

				// 根据状态标志设置显示选项
				switch flag {
				case 0x00:
					m.status.StatOpt = StatOptIdle
				case 0x01:
					m.status.StatOpt = StatOptForceShot
				case 0x02:
					m.status.StatOpt = StatOptForceHeat1
				case 0x03:
					m.status.StatOpt = StatOptForceHeat1Shot
				case 0x04:
					m.status.StatOpt = StatOptForceHeat2
				case 0x05:
					m.status.StatOpt = StatOptForceHeat2Shot
				case 0x06:
					m.status.StatOpt = StatOptForceHeat3
				case 0x07:
					m.status.StatOpt = StatOptForceHeat3Shot
				}
			}
		}

		// 2. 查看模式下的处理
		else if mode == MenuModeView {
			// TODO: 实现查看模式的优先级处理
		}

		// 3. 菜单模式下的处理
		else if mode == MenuModeMenu {
			// TODO: 实现菜单模式的优先级处理
		}

		// 4. 提示模式下的处理
		else if mode == MenuModeTip {
			// TODO: 实现提示模式的优先级处理
		}
	*/
}

// showStat 显示状态
func (m *Menu) showStat() {
	switch m.status.StatOpt {
	case StatOptIdle:
		// 显示"----"
		if m.status.DispCnter%2 == 0 {
			m.display.ShowPattern([]byte{
				SegG, SegG, SegG, SegG,
			})
		} else {
			m.display.Clear()
		}
	case StatOptAutoHeat1:
		// 显示"A.III"
		if m.status.DispCnter%2 == 0 {
			m.display.ShowText("A   ", true)
		} else {
			m.display.ShowText("A   ", false)
		}
		// 动态显示加热动画
		pattern := []byte{0, 0, 0, 0}
		switch m.status.DispCnter % 3 {
		case 0:
			pattern[1] = SegE
			pattern[2] = SegE
			pattern[3] = SegE
		case 1:
			pattern[1] = SegE | SegG
			pattern[2] = SegE | SegG
			pattern[3] = SegE | SegG
		case 2:
			pattern[1] = SegE | SegG | SegB
			pattern[2] = SegE | SegG | SegB
			pattern[3] = SegE | SegG | SegB
		}
		m.display.ShowPattern(pattern)
	case StatOptAutoHeat2:
		// 显示"A.222"
		if m.status.DispCnter%2 == 0 {
			m.display.ShowText("A222", true)
		} else {
			m.display.ShowText("A222", false)
		}
	case StatOptAutoHeat3:
		// 显示"A.333"
		if m.status.DispCnter%2 == 0 {
			m.display.ShowText("A333", true)
		} else {
			m.display.ShowText("A333", false)
		}
	case StatOptAutoShot:
		// 显示"A.---"
		if m.status.DispCnter%2 == 0 {
			m.display.ShowText("A---", true)
		} else {
			m.display.ShowText("A---", false)
		}
	case StatOptWarn:
		// 显示"E.XX"（XX为错误代码）
		if m.status.DispCnter%2 == 0 {
			m.display.ShowText("E  ", true)
		} else {
			m.display.ShowText("E  ", false)
		}
	}
}

// showView 显示查看内容
func (m *Menu) showView() {
	switch m.status.ViewOpt {
	case ViewOptTemperature:
		// 显示"t.XXX"（XXX为温度值）
		m.display.ShowText("t250", true)
	case ViewOptDuty:
		// 显示"P.XXX"（XXX为功率值）
		m.display.ShowText("P100", true)
	case ViewOptSmokeSensor:
		// 显示"S.XXX"（XXX为烟感值）
		m.display.ShowText("S123", true)
	case ViewOptOilData:
		// 显示"O.XXX"（XXX为油量值）
		m.display.ShowText("O456", true)
	}
}

// showMenu 显示菜单
func (m *Menu) showMenu() {
	switch m.status.MenuOpt {
	case MenuOptT0:
		m.display.ShowText("t0", false)
	case MenuOptT1:
		m.display.ShowText("t1", false)
	case MenuOptT2:
		m.display.ShowText("t2", false)
	case MenuOptT3:
		m.display.ShowText("t3", false)
	case MenuOptT4:
		m.display.ShowText("t4", false)
	case MenuOptT5:
		m.display.ShowText("t5", false)
	case MenuOptP0:
		m.display.ShowText("p0", false)
	case MenuOptP1:
		m.display.ShowText("p1", false)
	case MenuOptPDef:
		m.display.ShowText("pd", false)
	case MenuOptOilLimit:
		m.display.ShowText("ol", false)
	case MenuOptWaterLimit:
		m.display.ShowText("wl", false)
	}
}

// showTip 显示提示
func (m *Menu) showTip() {
	switch m.status.TipOpt {
	case TipOptOK:
		m.display.ShowText("OK", false)
	case TipOptErr:
		m.display.ShowText("ERR", false)
	case TipOptBLEUpgradeApp:
		// 显示升级动画
		pattern := []byte{0, 0, 0, 0}
		switch m.status.DispCnter % 6 {
		case 0:
			pattern[0] = SegA
		case 1:
			pattern[0] = SegA | SegB
		case 2:
			pattern[0] = SegA | SegB | SegC
		case 3:
			pattern[0] = SegA | SegB | SegC | SegD
		case 4:
			pattern[0] = SegA | SegB | SegC | SegD | SegE
		case 5:
			pattern[0] = SegA | SegB | SegC | SegD | SegE | SegF
		}
		m.display.ShowPattern(pattern)
	}
}

// OnShortPress 处理短按
func (m *Menu) OnShortPress() {
	m.mu.Lock()
	defer m.mu.Unlock()

	switch m.status.Mode {
	case MenuModeStat:
		m.status.Mode = MenuModeView
	case MenuModeView:
		m.status.ViewOpt = (m.status.ViewOpt + 1) % 4
	case MenuModeMenu:
		m.status.MenuOpt = (m.status.MenuOpt + 1) % 11
	case MenuModeTip:
		m.status.Mode = MenuModeStat
	}
	m.updateDisplay()
}

// OnLongPress 处理长按
func (m *Menu) OnLongPress() {
	m.mu.Lock()
	defer m.mu.Unlock()

	switch m.status.Mode {
	case MenuModeStat:
		m.status.Mode = MenuModeMenu
	case MenuModeView:
		m.status.Mode = MenuModeStat
	case MenuModeMenu:
		// TODO: 执行菜单项操作
		m.status.Mode = MenuModeStat
	case MenuModeTip:
		m.status.Mode = MenuModeStat
	}
	m.updateDisplay()
}

// OnSuperLongPress 处理超长按
func (m *Menu) OnSuperLongPress() {
	m.mu.Lock()
	defer m.mu.Unlock()

	// 超长按返回状态模式
	m.status.Mode = MenuModeStat
	m.status.StatOpt = StatOptIdle
	m.updateDisplay()
}

// SendMsg 发送菜单消息
func (m *Menu) SendMsg(msg MenuMsg) {
	select {
	case m.msgCh <- msg:
	default:
		// 消息队列满时丢弃
	}
}

// Close 关闭菜单
func (m *Menu) Close() {
	close(m.quit)  // 先发送退出信号
	close(m.msgCh) // 然后关闭消息通道
}
